﻿using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using System.IO;
using UnityEditor.AddressableAssets.Settings;
using UnityEditor.AddressableAssets;
using UnityEngine.ResourceManagement.ResourceLocations;

public class FileHashBundleCopyUtil
{
    static Dictionary<string, AddressableAssetEntry> addressDic = new Dictionary<string, AddressableAssetEntry>();

    static void CalUseEnty()
    {
        addressDic.Clear();

        AddressableAssetSettings aaStting = AddressableAssetSettingsDefaultObject.Settings;
        List<AddressableAssetEntry> entryList = new List<AddressableAssetEntry>();
        aaStting.GetAllAssets(entryList, true);

        int cnt = entryList.Count;
        for (int i = 0; i < cnt; i++)
        {
            AddressableAssetEntry itm = entryList[i];

            EditorUtility.DisplayProgressBar("Check Dep", itm.address, (i + 1) * 1.0f / cnt * 1.0f);

            //if (!itm.address.StartsWith("ClientRes/"))
                //if (!itm.address.StartsWith("ClientRes/"))
                    //continue;

                CalUseEntyItem(itm,"default");
        }
    }

    static void CalUseEntyItem(AddressableAssetEntry itmEntry,string label = null)
    {
        if (label != null && !itmEntry.labels.Contains(label))
            return;

        string key = itmEntry.address.Replace("Assets/", "").ToLower();
        key = key.Replace(" ","");

        AddressableAssetEntry tmpEntry;
        if (addressDic.TryGetValue(key, out tmpEntry))
            return;

        addressDic.Add(key, itmEntry);

        string[] dys = AssetDatabase.GetDependencies(itmEntry.AssetPath);
        AddressableAssetSettings aaStting = AddressableAssetSettingsDefaultObject.Settings;

        int cnt = dys.Length;
        for (int i = 0; i < cnt; i++)
        {
            string guid = AssetDatabase.AssetPathToGUID(dys[i]);
            AddressableAssetEntry dyEntry = aaStting.FindAssetEntry(guid);
        
            if (dyEntry == itmEntry || dyEntry == null)
                continue;

            //key = dyEntry.address.Replace("Assets/", "").ToLower();

            //if (addressDic.TryGetValue(key, out tmpEntry))
            //    continue;

            CalUseEntyItem(dyEntry);
        }
    }

    //[MenuItem("DefaultBundl/333")]
    //static void xxx()
    //{
    //    string uKey = "ssss/xxdee_dafer.bundle";
    //    int sIndex = uKey.LastIndexOf("_");
    //    string hash = uKey.Substring(sIndex + 1).Replace(".bundle", "");
    //    Debug.LogError(hash);
    //}
    // Start is called before the first frame update
    //[MenuItem("DefaultBundle/CopyTest")]
    public static void CopyAppendHashNameFileToStream()
    {
        //string platName = Platform.name;
        string platName = UnityEditor.EditorUserBuildSettings.activeBuildTarget.ToString();
        string orgPlatName = platName;
       
        string orgPath =  Application.dataPath + "/../ServerData/" + platName;

        switch (UnityEditor.EditorUserBuildSettings.activeBuildTarget)
        {
            case BuildTarget.StandaloneWindows: platName = Platform.name; break;
            case BuildTarget.StandaloneWindows64: platName = Platform.name; break;
        }

        string toPathRoot = Application.streamingAssetsPath + "/aa/" + platName + "/";

        if (!Directory.Exists(orgPath))
            return;

        if (PackageLabelData.IsAllPacakage)
        {
            string[] allFiles = Directory.GetFiles(orgPath,"*.bundle",SearchOption.AllDirectories);

            int icnt = allFiles.Length;
            for(int i = 0; i < icnt;i++)
            {
                string itmF = allFiles[i];
                EditorUtility.DisplayProgressBar("Copy", itmF, (i + 1) * 1.0f / icnt * 1.0f);

                int aIndex = itmF.IndexOf(orgPlatName);
                string itemToPath = GStringBuilder.Contact(Application.streamingAssetsPath, "/aa/", platName,"/", itmF.Remove(0,aIndex + orgPlatName.Length));
                string itemToDir = Path.GetDirectoryName(itemToPath);

                if (!Directory.Exists(itemToDir))
                    Directory.CreateDirectory(itemToDir);

                if (File.Exists(itemToPath))
                    continue;

                File.Copy(allFiles[i], itemToPath);
            }

            EditorUtility.ClearProgressBar();

            return;
        }

        //CalUseEnty();
        AddressableAssetSettings setting = AddressableAssetSettingsDefaultObject.Settings;
        bool cb;
        string jsonPath = GStringBuilder.Contact(Application.dataPath,"/../ServerData/",orgPlatName,"/catalog_", setting.PlayerBuildVersion,".json");
        List<IResourceLocation> resList = AddressablesUtil.GetDependenciesByCatalog(jsonPath,"default");
        int rnt = resList.Count;
        Dictionary<string, bool> internalDic = new Dictionary<string, bool>();
        for (int i = 0; i < rnt; i++)
        {
            string fname = Path.GetFileName(resList[i].InternalId);
            if (!internalDic.TryGetValue(fname, out cb))
                internalDic.Add(fname, true);
        }

        if (!Directory.Exists(toPathRoot))
            Directory.CreateDirectory(toPathRoot);

        //string paltName = "Android";
        Dictionary<string, bool> fileDic = new Dictionary<string, bool>();
        string[] files = Directory.GetFiles(orgPath,"*.bundle",SearchOption.AllDirectories);
        int fnt = files.Length;
        for(int i = 0; i < fnt;i++)
        {
            string prekey = files[i];
            string hash;
            string gpName;

            //if (prekey.IndexOf("91cd5f5b0fb3a41d156438c268ff75da") != -1)
            //    Debug.LogError(2);

            EditorUtility.DisplayProgressBar("Copy",prekey,(i + 1)*1.0f / fnt*1.0f);

            if(prekey.IndexOf("_unitybuiltinshaders") != -1 || prekey.IndexOf("_all_") != -1)
            {
                string toShaderPath = toPathRoot + Path.GetFileName(prekey);

                if (File.Exists(toShaderPath))
                    File.Delete(toShaderPath);

                File.Copy(prekey, toShaderPath);
                continue;
            }

            bool tmpB;
            string fname = Path.GetFileName(files[i]);
            if (!internalDic.TryGetValue(fname, out tmpB))
                continue;

            //PraseFileName(ref prekey, out hash,out gpName);
            //string address = RejectHash(prekey);
            //if (address == null) continue;
            //AddressableAssetEntry itmEntry;
            //if (!addressDic.TryGetValue(address, out itmEntry))
            //    continue;
            //if (prekey == null)
            //    continue;

            //string itemToPath = GStringBuilder.Contact(toPathRoot,gpName,"/",prekey);
            int aIndex = files[i].IndexOf(orgPlatName);
            string itemToPath = GStringBuilder.Contact(Application.streamingAssetsPath, "/aa/", platName, "/", files[i].Remove(0, aIndex + orgPlatName.Length));
            string itemToDir = Path.GetDirectoryName(itemToPath);

            if (!Directory.Exists(itemToDir))
                Directory.CreateDirectory(itemToDir);

            if (File.Exists(itemToPath))
                continue;

            File.Copy(files[i], itemToPath);
        }

        addressDic.Clear();
        EditorUtility.ClearProgressBar();
    }

    public static void PraseFileName(ref string fileName, out string hash,out string gpName)
    {
        string platName = "Android/";
        string assName = "_assets";
        string sceneName = "_scenes";

        fileName = fileName.Replace("\\","/");

        int assIndex = fileName.LastIndexOf(assName);
        int sceneIndex = fileName.LastIndexOf(sceneName);

        if(sceneIndex != -1)
        {
            assName = sceneName;
            assIndex = sceneIndex;
        }

        if (assIndex == -1)
        {
            hash = null;
            gpName = null;
            fileName = null;
            return;
        }

        int pIndex = fileName.IndexOf(platName);
        gpName = fileName.Substring(pIndex + platName.Length);
        int gAssIndex = gpName.IndexOf(assName);
        gpName = gpName.Remove(gAssIndex + assName.Length);

        int index2 = gpName.IndexOf("_");
        gpName = gpName.Remove(index2);

        int index = fileName.LastIndexOf("_");
        hash = fileName.Substring(index + 1).Replace(".bundle", "");

        fileName = fileName.Substring(assIndex + assName.Length + 1);
    }

    public static string RejectHash(string file)
    {
        if (null == file) return null;

        int index = file.LastIndexOf("_");
        int index2 = file.LastIndexOf(".");

        return file.Remove(index,index2 - index).Replace(".bundle","");
    }
}
